package com.zhuoyue.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.zhuoyue.biz.core.api.dao.DeviceDao;
import com.zhuoyue.biz.core.api.dao.InfraredDeviceDao;
import com.zhuoyue.biz.core.api.dao.LocalSceneDao;
import com.zhuoyue.biz.core.api.domain.*;
import com.zhuoyue.biz.core.api.dto.req.CommonReq;
import com.zhuoyue.biz.core.api.dto.req.InfraredReq;
import com.zhuoyue.biz.core.api.dto.req.JointReq;
import com.zhuoyue.biz.core.api.service.GatewayRedisService;
import com.zhuoyue.biz.core.api.service.OdStructureService;
import com.zhuoyue.biz.core.command.cmd.common.infrared.Infrared;
import com.zhuoyue.biz.core.command.cmd.common.jointcontrol.Jointcontrol;
import com.zhuoyue.biz.core.command.cmd.common.scene.Scene;
import com.zhuoyue.biz.core.command.constant.LianKongBangDingPeiZhiControlCmdDeal;
import com.zhuoyue.common.aop.auth.CheckLogin;
import com.zhuoyue.common.constant.DeviceConstant;
import com.zhuoyue.common.dto.ControllerResult;

import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.utils.CmdUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;


/**
 * 更新数据帧2020/11/18
 * 1：更新方案参照zigbee测试环境
 * 2：去掉deviceType，统一采用zigbeeMac来查询需要控制设备类型，用action参数老用添加控制参数
 * 3：zigbee测试环境采用的表是：tbl_device_structure
 *
 * @author wjming
 */
@RestController
@Scope("prototype")
@RequestMapping("/api/cmd")
@Validated
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AppCmdController {

    private final GatewayRedisService gatewayRedisService;

    private final DeviceDao deviceDao;

    private final LocalSceneDao localSceneDao;

    private final InfraredDeviceDao infraredDeviceDao;

    private final OdStructureService odStructureService;

    private static final String START_2A = "2A";
    private static final String END_23 = "23";

    /**
     * 设备数据帧指令处理
     * 包括：设备开关控制,模式控制.风速控制等
     *
     * @param commonReq
     * @return
     */
    @PostMapping(value = "/device/deal")
    public ControllerResult cmdDeviceSend(@RequestBody CommonReq commonReq) {
        log.info("request -> [cmdDeviceSend] -> [commonReq:{}]", JSONObject.toJSONString(commonReq));
        DeviceAndGatewayDO deviceAndGatewayDO = deviceDao.selectUseCmdByMac(commonReq.getDeviceId());
        if (deviceAndGatewayDO == null || deviceAndGatewayDO.getHomeId() == null) {
            return ControllerResult.toParamFail("请确认设备是否正确配置");
        }
        //获取cmd
        String cmd = odStructureService.structureCmd(deviceAndGatewayDO, commonReq.getControlParam());
        String gatewayMac = deviceAndGatewayDO.getGatewayMac();
        log.info("result ->[{}] [cmdDeviceSend] -> [{}]", gatewayMac, cmd);
        return control(commonReq.getPurpose(), cmd, gatewayMac);
    }


    @PostMapping(value = "/infrared/deal")
    public ControllerResult cmdInfraredSend(@RequestBody InfraredReq infraredReq) {
        log.info("request -> [cmdInfraredSend] -> [infraredReq:{}]", JSONObject.toJSONString(infraredReq));
        InfraredDeviceControlDO infrared = infraredDeviceDao.selectInfraredDeviceMessageById(infraredReq.getDeviceId());
        if (infrared == null) {
            throw new ZyServerException(ErrorType.result_not_exist);
        }
        String cmd = Infrared.control(infrared, infraredReq.getControlParam());
        String gatewayMac = infrared.getGatewayMac();
        log.info("result -> [cmdDeviceSend] -> [{}] ->[{}]", gatewayMac, cmd);
        return control(infraredReq.getPurpose(), cmd, gatewayMac);
    }


    /**
     * 场景数据帧指令处理
     *
     * @param
     * @param
     * @return
     */
    @PostMapping("/scene/deal")
    public ControllerResult cmdSceneSend(@RequestBody CommonReq commonReq) {
        log.info("request -> [cmdSceneSend] -> [commonReq:{}]", JSONObject.toJSONString(commonReq));
        LocalSceneDO localSceneDO = localSceneDao.selectById(commonReq.getDeviceId());
        if (localSceneDO == null) {
            return ControllerResult.toParamFail("场景不存在或已被删除");
        }
        if (localSceneDO.getHomeId() == null) {
            return ControllerResult.toParamFail("场景未绑定家庭，请刷新后重试");
        }

        //获取cmd
        String cmd = Scene.control(localSceneDO, commonReq.getControlParam());
        if (StringUtils.isEmpty(cmd)) {
            return ControllerResult.toParamFail("参数错误");
        }
        String gatewayMac = localSceneDO.getGatewayMac();
        log.info("result -> [cmdSceneSend] -> [{}] ->[{}]", gatewayMac, cmd);
        return control(commonReq.getPurpose(), cmd, gatewayMac);
    }


    /**
     * 设备一键全关
     *
     * @param gatewayId
     * @return
     */
    @PostMapping("/close/all")
    @CheckLogin
    public ControllerResult closeAllDevice(@NotBlank(message = "网关Id不能为空") String gatewayId) {
        log.info("request -> [closeAllDevice] -> [gatewayId:{}]", gatewayId);
        List<DeviceDO> deviceDoS = deviceDao.selectOpenDeviceByGatewayId(gatewayId);
        if (CollectionUtils.isEmpty(deviceDoS)) {
            return ControllerResult.toParamFail("没有发现未关闭的设备哦!");
        }
        List<Object> objects = new ArrayList<>(40);
        deviceDoS.forEach(list -> {
            String device = list.getOdIndex() + list.getDeviceType() + list.getProductType();
            String cmd = "";
            String cmdStr = "";
            switch (device) {
                //一路面板
                case "0FAA0502":
                    cmd = "02ff00000000000000000FAAFF080001800305020102";
                    break;
                //一路联控面板
                case "0FAA0504":
                    cmd = "02ff00000000000000000FAAFF080001800305040102";
                    break;
                //二路面板
                case "0FAA0602":
                    cmd = "02ff00000000000000000FAAFF0A000D8003060201020102";
                    break;
                //二路联控面板
                case "0FAA0604":
                    cmd = "02FF00000000000000000FAAFF0A000D8003060401020102";
                    break;
                //三路面板
                case "0FAA0702":
                    cmd = "02FF00000000000000000FAAFF0C006D80030702010201020102";
                    break;
                //三路联控面板
                case "0FAA0704":
                    cmd = "02FF00000000000000000FAAFF0C006D80030704010201020102";
                    break;
                //四路联控面板
                case "0FAA0804":
                    cmd = "02FF00000000000000000FAAFF0E036D800308040102010201020102";
                    break;
                //多功能开关（极彩系列）
                case "0FAA8A09":
                    cmd = "02FF00000000000000000FAAFF0E036D80038A090102010201020102";
                    break;
                //双色温驱动
                case "0FAA0D02":
                    cmd = "02ff00000000000000000FAAFF131F0000030d0202000000000000000000000000";
                    break;
                //单色温
                case "0FAA0D03":
                    cmd = "02ff00000000000000000FAAFF131F0000030d0302000000000000000000000000";
                    break;
                //开关控制盒
                case "0FAA0D04":
                    cmd = "02ff00000000000000000FAAFF131F0000030d0402000000000000000000000000";
                    break;
                case "0FAB0602"://四路面板
                    cmd = "02FF00000000000000000FABFF0A002A8003060202020202";
                    break;
                //多彩灯带1.0
                case "0FAA0B02":
                    cmd = "02ff00000000000000000FAAFF08090000030b020102";
                    break;
                //开关控制盒
                case "0FAA0B03":
                    cmd = "02ff00000000000000000FAAFF08090000030b030102";
                    break;
                default:
                    break;

            }
            cmdStr = START_2A + CmdUtils.getDateLength(cmd) + cmd + CmdUtils.getCmdBodySum(cmd) + END_23;
            gatewayRedisService.writeDataToGateway(list.getGatewayMac(), cmdStr);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("result -> [closeAllDevice] -> [{}]", cmdStr);
        });

        return ControllerResult.toReturnDataSuccess(objects.size() + "", objects);
    }


    /**
     * 联控数据帧指令处理
     *
     * @param jointReq
     * @return
     */
    @PostMapping("/jointcontrol/deal")
    @CheckLogin
    public ControllerResult linkageConfiguration(@RequestBody JointReq jointReq) {
        log.info("request -> [linkageConfiguration] -> [jointReq:{}]", JSONObject.toJSONString(jointReq));
        DeviceAndGatewayDO sourceDevice = deviceDao.selectUseCmdByMac(jointReq.getSourceDeviceId());
        DeviceAndGatewayDO goalDevice = deviceDao.selectUseCmdByMac(jointReq.getGoalDeviceId());
        if (sourceDevice == null) {
            return ControllerResult.toParamFail("源设备不存在或已被删除");
        }
        if (goalDevice == null) {
            return ControllerResult.toParamFail("目标设备不存在或已被删除");
        }
        //获取cmd
        //如果是新增联控信息或者删除，那么正常走流程，如果清空，则只可直接控制，不可获取数据帧返回，因为要执行8遍
        String cmd = "";
        switch (jointReq.getControl().getControlType()) {
            //新增联控信息
            case LianKongBangDingPeiZhiControlCmdDeal.ControlType.ADD:
                //删除联控信息
            case LianKongBangDingPeiZhiControlCmdDeal.ControlType.DELETE:
                cmd = Jointcontrol.control(sourceDevice, goalDevice, jointReq.getControl());
                break;
            //清空联控信息，因为设备原因，需要通过循环的方式进行完全删除
            case LianKongBangDingPeiZhiControlCmdDeal.ControlType.CLEAR:

                String gatewayMac = sourceDevice.getGatewayMac();
                String cmdStr = "0201" + gatewayMac + sourceDevice + "177321" + sourceDevice.getProductType().split("_")[1] + "FFFFFFFFFFFFFFFFFFFFFFFF";
                String length = CmdUtils.getDateLength(cmdStr);
                String sum = CmdUtils.getCmdBodySum(cmdStr);
                String cmdClear = START_2A + length + cmdStr + sum + END_23;
                gatewayRedisService.writeDataToGateway(sourceDevice.getGatewayMac(), cmdClear);
                return ControllerResult.toReturnMessageSuccess("控制命令已发送");


            default://默认直接发送
                return ControllerResult.toParamFail("参数错误");
        }


        if (StringUtils.isEmpty(cmd)) {
            return ControllerResult.toParamFail("参数错误");
        }
        switch (jointReq.getPurpose()) {
            case DeviceConstant.RequestPurpose.GET_CMD:
                return ControllerResult.toReturnDataSuccess("数据帧生成成功", cmd);
            case DeviceConstant.RequestPurpose.CONTROL_DEVICE:
                gatewayRedisService.writeDataToGateway(sourceDevice.getGatewayMac(), cmd);
                return ControllerResult.toReturnMessageSuccess("控制命令已发送");
            default://默认直接发送
                return ControllerResult.toParamFail("参数错误");
        }
    }


    private ControllerResult control(String purpose, String cmd, String gatewayMac) {
        switch (purpose) {
            case DeviceConstant.RequestPurpose.GET_CMD:
                if (!StringUtils.startsWithIgnoreCase(cmd, START_2A) || !StringUtils.endsWithIgnoreCase(cmd, END_23)) {
                    cmd = START_2A + CmdUtils.getDateLength(cmd) + cmd + CmdUtils.getCmdBodySum(cmd) + END_23;
                }
                return ControllerResult.toReturnDataSuccess("数据帧生成成功", cmd);
            case DeviceConstant.RequestPurpose.CONTROL_DEVICE:
                gatewayRedisService.writeDataToGateway(gatewayMac, cmd);
                return ControllerResult.toReturnDataSuccess("控制命令已发送", null);
            default://默认直接发送
                return ControllerResult.toParamFail("参数错误");
        }
    }

}
